//
// Created by xuxu on 2020-07-05.
// tensorflow/tensorflow/lite/delegates/gpu/cl/opencl_wrapper.h
//

#ifndef OPENCL_WRAPPER_H
#define OPENCL_WRAPPER_H

#define CL_TARGET_OPENCL_VERSION 200

#include <CL/cl.h>
#include <CL/cl_egl.h>
#include <CL/cl_ext.h>
#include <CL/cl_gl.h>
#include <CL/cl_platform.h>


namespace mslite
{

void LoadOpenCL();

typedef cl_int(CL_API_CALL *PFN_clGetPlatformIDs)(
        cl_uint /* num_entries */, cl_platform_id * /* platforms */,
        cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clGetPlatformInfo)(
        cl_platform_id /* platform */, cl_platform_info /* param_name */,
        size_t /* param_value_size */, void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clGetDeviceIDs)(
        cl_platform_id /* platform */, cl_device_type /* device_type */,
        cl_uint /* num_entries */, cl_device_id * /* devices */,
        cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clGetDeviceInfo)(
        cl_device_id /* device */, cl_device_info /* param_name */,
        size_t /* param_value_size */, void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clCreateSubDevices)(
        cl_device_id /* in_device */,
        const cl_device_partition_property * /* properties */,
        cl_uint /* num_devices */, cl_device_id * /* out_devices */,
        cl_uint * /* num_devices_ret */) CL_API_SUFFIX__VERSION_1_2;
typedef cl_int(CL_API_CALL *PFN_clRetainDevice)(cl_device_id /* device */)
CL_API_SUFFIX__VERSION_1_2;
typedef cl_int(CL_API_CALL *PFN_clReleaseDevice)(cl_device_id /* device */)
CL_API_SUFFIX__VERSION_1_2;
typedef cl_context(CL_API_CALL *PFN_clCreateContext)(
        const cl_context_properties * /* properties */, cl_uint /* num_devices */,
        const cl_device_id * /* devices */,
        void(CL_CALLBACK * /* pfn_notify */)(const char *, const void *, size_t,
                                             void *),
        void * /* user_data */,
        cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_context(CL_API_CALL *PFN_clCreateContextFromType)(
        const cl_context_properties * /* properties */,
        cl_device_type /* device_type */,
        void(CL_CALLBACK * /* pfn_notify*/)(const char *, const void *, size_t,
                                            void *),
        void * /* user_data */,
        cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clRetainContext)(cl_context /* context */)
CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clReleaseContext)(cl_context /* context */)
CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clGetContextInfo)(
        cl_context /* context */, cl_context_info /* param_name */,
        size_t /* param_value_size */, void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_command_queue(CL_API_CALL *PFN_clCreateCommandQueueWithProperties)(
        cl_context /* context */, cl_device_id /* device */,
        const cl_queue_properties * /* properties */,
        cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_2_0;
typedef cl_int(CL_API_CALL *PFN_clRetainCommandQueue)(
        cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clReleaseCommandQueue)(
        cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clGetCommandQueueInfo)(
        cl_command_queue /* command_queue */,
        cl_command_queue_info /* param_name */, size_t /* param_value_size */,
        void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_mem(CL_API_CALL *PFN_clCreateBuffer)(
        cl_context /* context */, cl_mem_flags /* flags */, size_t /* size */,
        void * /* host_ptr */,
        cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_mem(CL_API_CALL *PFN_clCreateSubBuffer)(
        cl_mem /* buffer */, cl_mem_flags /* flags */,
        cl_buffer_create_type /* buffer_create_type */,
        const void * /* buffer_create_info */,
        cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1;
typedef cl_mem(CL_API_CALL *PFN_clCreateImage)(
        cl_context /* context */, cl_mem_flags /* flags */,
        const cl_image_format * /* image_format */,
        const cl_image_desc * /* image_desc */, void * /* host_ptr */,
        cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2;
typedef cl_mem(CL_API_CALL *PFN_clCreatePipe)(
        cl_context /* context */, cl_mem_flags /* flags */,
        cl_uint /* pipe_packet_size */, cl_uint /* pipe_max_packets */,
        const cl_pipe_properties * /* properties */,
        cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_2_0;
typedef cl_int(CL_API_CALL *PFN_clRetainMemObject)(cl_mem /* memobj */)
CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clReleaseMemObject)(cl_mem /* memobj */)
CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clGetSupportedImageFormats)(
        cl_context /* context */, cl_mem_flags /* flags */,
        cl_mem_object_type /* image_type */, cl_uint /* num_entries */,
        cl_image_format * /* image_formats */,
        cl_uint * /* num_image_formats */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clGetMemObjectInfo)(
        cl_mem /* memobj */, cl_mem_info /* param_name */,
        size_t /* param_value_size */, void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clGetImageInfo)(
        cl_mem /* image */, cl_image_info /* param_name */,
        size_t /* param_value_size */, void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clGetPipeInfo)(
        cl_mem /* pipe */, cl_pipe_info /* param_name */,
        size_t /* param_value_size */, void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_2_0;
typedef cl_int(CL_API_CALL *PFN_clSetMemObjectDestructorCallback)(
        cl_mem /* memobj */,
        void(CL_CALLBACK * /*pfn_notify*/)(cl_mem /* memobj */,
                                           void * /*user_data*/),
        void * /*user_data */) CL_API_SUFFIX__VERSION_1_1;
typedef void *(CL_API_CALL *PFN_clSVMAlloc)(
        cl_context /* context */, cl_svm_mem_flags /* flags */, size_t /* size */,
        cl_uint /* alignment */)CL_API_SUFFIX__VERSION_2_0;
typedef void(CL_API_CALL *PFN_clSVMFree)(cl_context /* context */,
                                         void * /* svm_pointer */)
CL_API_SUFFIX__VERSION_2_0;
typedef cl_sampler(CL_API_CALL *PFN_clCreateSamplerWithProperties)(
        cl_context /* context */,
        const cl_sampler_properties * /* normalized_coords */,
        cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_2_0;
typedef cl_int(CL_API_CALL *PFN_clRetainSampler)(cl_sampler /* sampler */)
CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clReleaseSampler)(cl_sampler /* sampler */)
CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clGetSamplerInfo)(
        cl_sampler /* sampler */, cl_sampler_info /* param_name */,
        size_t /* param_value_size */, void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_program(CL_API_CALL *PFN_clCreateProgramWithSource)(
        cl_context /* context */, cl_uint /* count */, const char ** /* strings */,
        const size_t * /* lengths */,
        cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_program(CL_API_CALL *PFN_clCreateProgramWithBinary)(
        cl_context /* context */, cl_uint /* num_devices */,
        const cl_device_id * /* device_list */, const size_t * /* lengths */,
        const unsigned char ** /* binaries */, cl_int * /* binary_status */,
        cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_program(CL_API_CALL *PFN_clCreateProgramWithBuiltInKernels)(
        cl_context /* context */, cl_uint /* num_devices */,
        const cl_device_id * /* device_list */, const char * /* kernel_names */,
        cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2;
typedef cl_int(CL_API_CALL *PFN_clRetainProgram)(cl_program /* program */)
CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clReleaseProgram)(cl_program /* program */)
CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clBuildProgram)(
        cl_program /* program */, cl_uint /* num_devices */,
        const cl_device_id * /* device_list */, const char * /* options */,
        void(CL_CALLBACK * /* pfn_notify */)(cl_program /* program */,
                                             void * /* user_data */),
        void * /* user_data */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clCompileProgram)(
        cl_program /* program */, cl_uint /* num_devices */,
        const cl_device_id * /* device_list */, const char * /* options */,
        cl_uint /* num_input_headers */, const cl_program * /* input_headers */,
        const char ** /* header_include_names */,
        void(CL_CALLBACK * /* pfn_notify */)(cl_program /* program */,
                                             void * /* user_data */),
        void * /* user_data */) CL_API_SUFFIX__VERSION_1_2;
typedef cl_program(CL_API_CALL *PFN_clLinkProgram)(
        cl_context /* context */, cl_uint /* num_devices */,
        const cl_device_id * /* device_list */, const char * /* options */,
        cl_uint /* num_input_programs */, const cl_program * /* input_programs */,
        void(CL_CALLBACK * /* pfn_notify */)(cl_program /* program */,
                                             void * /* user_data */),
        void * /* user_data */,
        cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2;
typedef cl_int(CL_API_CALL *PFN_clUnloadPlatformCompiler)(
        cl_platform_id /* platform */) CL_API_SUFFIX__VERSION_1_2;
typedef cl_int(CL_API_CALL *PFN_clGetProgramInfo)(
        cl_program /* program */, cl_program_info /* param_name */,
        size_t /* param_value_size */, void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clGetProgramBuildInfo)(
        cl_program /* program */, cl_device_id /* device */,
        cl_program_build_info /* param_name */, size_t /* param_value_size */,
        void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_kernel(CL_API_CALL *PFN_clCreateKernel)(
        cl_program /* program */, const char * /* kernel_name */,
        cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clCreateKernelsInProgram)(
        cl_program /* program */, cl_uint /* num_kernels */,
        cl_kernel * /* kernels */,
        cl_uint * /* num_kernels_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clRetainKernel)(cl_kernel /* kernel */)
CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clReleaseKernel)(cl_kernel /* kernel */)
CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clSetKernelArg)(
        cl_kernel /* kernel */, cl_uint /* arg_index */, size_t /* arg_size */,
        const void * /* arg_value */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clSetKernelArgSVMPointer)(
        cl_kernel /* kernel */, cl_uint /* arg_index */,
        const void * /* arg_value */) CL_API_SUFFIX__VERSION_2_0;
typedef cl_int(CL_API_CALL *PFN_clSetKernelExecInfo)(
        cl_kernel /* kernel */, cl_kernel_exec_info /* param_name */,
        size_t /* param_value_size */,
        const void * /* param_value */) CL_API_SUFFIX__VERSION_2_0;
typedef cl_int(CL_API_CALL *PFN_clGetKernelInfo)(
        cl_kernel /* kernel */, cl_kernel_info /* param_name */,
        size_t /* param_value_size */, void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clGetKernelArgInfo)(
        cl_kernel /* kernel */, cl_uint /* arg_indx */,
        cl_kernel_arg_info /* param_name */, size_t /* param_value_size */,
        void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_2;
typedef cl_int(CL_API_CALL *PFN_clGetKernelWorkGroupInfo)(
        cl_kernel /* kernel */, cl_device_id /* device */,
        cl_kernel_work_group_info /* param_name */, size_t /* param_value_size */,
        void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clWaitForEvents)(
        cl_uint /* num_events */,
        const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clGetEventInfo)(
        cl_event /* event */, cl_event_info /* param_name */,
        size_t /* param_value_size */, void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_event(CL_API_CALL *PFN_clCreateUserEvent)(cl_context /* context */,
                                                     cl_int * /* errcode_ret */)
CL_API_SUFFIX__VERSION_1_1;
typedef cl_int(CL_API_CALL *PFN_clRetainEvent)(cl_event /* event */)
CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clReleaseEvent)(cl_event /* event */)
CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clSetUserEventStatus)(
        cl_event /* event */,
        cl_int /* execution_status */) CL_API_SUFFIX__VERSION_1_1;
typedef cl_int(CL_API_CALL *PFN_clSetEventCallback)(
        cl_event /* event */, cl_int /* command_exec_callback_type */,
        void(CL_CALLBACK * /* pfn_notify */)(cl_event, cl_int, void *),
        void * /* user_data */) CL_API_SUFFIX__VERSION_1_1;
typedef cl_int(CL_API_CALL *PFN_clGetEventProfilingInfo)(
        cl_event /* event */, cl_profiling_info /* param_name */,
        size_t /* param_value_size */, void * /* param_value */,
        size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clFlush)(cl_command_queue /* command_queue */)
CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clFinish)(cl_command_queue /* command_queue */)
CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueReadBuffer)(
        cl_command_queue /* command_queue */, cl_mem /* buffer */,
        cl_bool /* blocking_read */, size_t /* offset */, size_t /* size */,
        void * /* ptr */, cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueReadBufferRect)(
        cl_command_queue /* command_queue */, cl_mem /* buffer */,
        cl_bool /* blocking_read */, const size_t * /* buffer_offset */,
        const size_t * /* host_offset */, const size_t * /* region */,
        size_t /* buffer_row_pitch */, size_t /* buffer_slice_pitch */,
        size_t /* host_row_pitch */, size_t /* host_slice_pitch */,
        void * /* ptr */, cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
typedef cl_int(CL_API_CALL *PFN_clEnqueueWriteBuffer)(
        cl_command_queue /* command_queue */, cl_mem /* buffer */,
        cl_bool /* blocking_write */, size_t /* offset */, size_t /* size */,
        const void * /* ptr */, cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueWriteBufferRect)(
        cl_command_queue /* command_queue */, cl_mem /* buffer */,
        cl_bool /* blocking_write */, const size_t * /* buffer_offset */,
        const size_t * /* host_offset */, const size_t * /* region */,
        size_t /* buffer_row_pitch */, size_t /* buffer_slice_pitch */,
        size_t /* host_row_pitch */, size_t /* host_slice_pitch */,
        const void * /* ptr */, cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
typedef cl_int(CL_API_CALL *PFN_clEnqueueFillBuffer)(
        cl_command_queue /* command_queue */, cl_mem /* buffer */,
        const void * /* pattern */, size_t /* pattern_size */, size_t /* offset */,
        size_t /* size */, cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2;
typedef cl_int(CL_API_CALL *PFN_clEnqueueCopyBuffer)(
        cl_command_queue /* command_queue */, cl_mem /* src_buffer */,
        cl_mem /* dst_buffer */, size_t /* src_offset */, size_t /* dst_offset */,
        size_t /* size */, cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueCopyBufferRect)(
        cl_command_queue /* command_queue */, cl_mem /* src_buffer */,
        cl_mem /* dst_buffer */, const size_t * /* src_origin */,
        const size_t * /* dst_origin */, const size_t * /* region */,
        size_t /* src_row_pitch */, size_t /* src_slice_pitch */,
        size_t /* dst_row_pitch */, size_t /* dst_slice_pitch */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
typedef cl_int(CL_API_CALL *PFN_clEnqueueReadImage)(
        cl_command_queue /* command_queue */, cl_mem /* image */,
        cl_bool /* blocking_read */, const size_t * /* origin[3] */,
        const size_t * /* region[3] */, size_t /* row_pitch */,
        size_t /* slice_pitch */, void * /* ptr */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueWriteImage)(
        cl_command_queue /* command_queue */, cl_mem /* image */,
        cl_bool /* blocking_write */, const size_t * /* origin[3] */,
        const size_t * /* region[3] */, size_t /* input_row_pitch */,
        size_t /* input_slice_pitch */, const void * /* ptr */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueFillImage)(
        cl_command_queue /* command_queue */, cl_mem /* image */,
        const void * /* fill_color */, const size_t * /* origin[3] */,
        const size_t * /* region[3] */, cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2;
typedef cl_int(CL_API_CALL *PFN_clEnqueueCopyImage)(
        cl_command_queue /* command_queue */, cl_mem /* src_image */,
        cl_mem /* dst_image */, const size_t * /* src_origin[3] */,
        const size_t * /* dst_origin[3] */, const size_t * /* region[3] */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueCopyImageToBuffer)(
        cl_command_queue /* command_queue */, cl_mem /* src_image */,
        cl_mem /* dst_buffer */, const size_t * /* src_origin[3] */,
        const size_t * /* region[3] */, size_t /* dst_offset */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueCopyBufferToImage)(
        cl_command_queue /* command_queue */, cl_mem /* src_buffer */,
        cl_mem /* dst_image */, size_t /* src_offset */,
        const size_t * /* dst_origin[3] */, const size_t * /* region[3] */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
typedef void *(CL_API_CALL *PFN_clEnqueueMapBuffer)(
        cl_command_queue /* command_queue */, cl_mem /* buffer */,
        cl_bool /* blocking_map */, cl_map_flags /* map_flags */,
        size_t /* offset */, size_t /* size */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */, cl_event * /* event */,
        cl_int * /* errcode_ret */)CL_API_SUFFIX__VERSION_1_0;
typedef void *(CL_API_CALL *PFN_clEnqueueMapImage)(
        cl_command_queue /* command_queue */, cl_mem /* image */,
        cl_bool /* blocking_map */, cl_map_flags /* map_flags */,
        const size_t * /* origin[3] */, const size_t * /* region[3] */,
        size_t * /* image_row_pitch */, size_t * /* image_slice_pitch */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */, cl_event * /* event */,
        cl_int * /* errcode_ret */)CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueUnmapMemObject)(
        cl_command_queue /* command_queue */, cl_mem /* memobj */,
        void * /* mapped_ptr */, cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueMigrateMemObjects)(
        cl_command_queue /* command_queue */, cl_uint /* num_mem_objects */,
        const cl_mem * /* mem_objects */, cl_mem_migration_flags /* flags */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2;
typedef cl_int(CL_API_CALL *PFN_clEnqueueNDRangeKernel)(
        cl_command_queue /* command_queue */, cl_kernel /* kernel */,
        cl_uint /* work_dim */, const size_t * /* global_work_offset */,
        const size_t * /* global_work_size */, const size_t * /* local_work_size */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueNativeKernel)(
        cl_command_queue /* command_queue */,
        void(CL_CALLBACK * /*user_func*/)(void *), void * /* args */,
        size_t /* cb_args */, cl_uint /* num_mem_objects */,
        const cl_mem * /* mem_list */, const void ** /* args_mem_loc */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueMarkerWithWaitList)(
        cl_command_queue /* command_queue */, cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2;
typedef cl_int(CL_API_CALL *PFN_clEnqueueBarrierWithWaitList)(
        cl_command_queue /* command_queue */, cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2;
typedef cl_int(CL_API_CALL *PFN_clEnqueueSVMFree)(
        cl_command_queue /* command_queue */, cl_uint /* num_svm_pointers */,
        void *[] /* svm_pointers[] */,
        void(CL_CALLBACK * /*pfn_free_func*/)(cl_command_queue /* queue */,
                                              cl_uint /* num_svm_pointers */,
                                              void *[] /* svm_pointers[] */,
                                              void * /* user_data */),
        void * /* user_data */, cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_2_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueSVMMemcpy)(
        cl_command_queue /* command_queue */, cl_bool /* blocking_copy */,
        void * /* dst_ptr */, const void * /* src_ptr */, size_t /* size */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_2_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueSVMMemFill)(
        cl_command_queue /* command_queue */, void * /* svm_ptr */,
        const void * /* pattern */, size_t /* pattern_size */, size_t /* size */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_2_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueSVMMap)(
        cl_command_queue /* command_queue */, cl_bool /* blocking_map */,
        cl_map_flags /* flags */, void * /* svm_ptr */, size_t /* size */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_2_0;
typedef cl_int(CL_API_CALL *PFN_clEnqueueSVMUnmap)(
        cl_command_queue /* command_queue */, void * /* svm_ptr */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_2_0;
typedef void *(CL_API_CALL *PFN_clGetExtensionFunctionAddressForPlatform)(
        cl_platform_id /* platform */,
        const char * /* func_name */)CL_API_SUFFIX__VERSION_1_2;
typedef cl_mem(CL_API_CALL *PFN_clCreateImage2D)(
        cl_context /* context */, cl_mem_flags /* flags */,
        const cl_image_format * /* image_format */, size_t /* image_width */,
        size_t /* image_height */, size_t /* image_row_pitch */,
        void * /* host_ptr */, cl_int * /* errcode_ret */);
typedef cl_mem(CL_API_CALL *PFN_clCreateImage3D)(
        cl_context /* context */, cl_mem_flags /* flags */,
        const cl_image_format * /* image_format */, size_t /* image_width */,
        size_t /* image_height */, size_t /* image_depth */,
        size_t /* image_row_pitch */, size_t /* image_slice_pitch */,
        void * /* host_ptr */, cl_int * /* errcode_ret */);
typedef cl_int(CL_API_CALL *PFN_clEnqueueMarker)(
        cl_command_queue /* command_queue */, cl_event * /* event */);
typedef cl_int(CL_API_CALL *PFN_clEnqueueWaitForEvents)(
        cl_command_queue /* command_queue */, cl_uint /* num_events */,
        const cl_event * /* event_list */);
typedef cl_int(CL_API_CALL *PFN_clEnqueueBarrier)(
        cl_command_queue /* command_queue */);
typedef cl_int(CL_API_CALL *PFN_clUnloadCompiler)();
typedef void *(CL_API_CALL *PFN_clGetExtensionFunctionAddress)(
        const char * /* func_name */);
typedef cl_command_queue(CL_API_CALL *PFN_clCreateCommandQueue)(
        cl_context /* context */, cl_device_id /* device */,
        cl_command_queue_properties /* properties */, cl_int * /* errcode_ret */);
typedef cl_sampler(CL_API_CALL *PFN_clCreateSampler)(
        cl_context /* context */, cl_bool /* normalized_coords */,
        cl_addressing_mode /* addressing_mode */, cl_filter_mode /* filter_mode */,
        cl_int * /* errcode_ret */);
typedef cl_int(CL_API_CALL *PFN_clEnqueueTask)(
        cl_command_queue /* command_queue */, cl_kernel /* kernel */,
        cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */, cl_event * /* event */);

// OpenGL sharing
typedef cl_mem(CL_API_CALL *PFN_clCreateFromGLBuffer)(cl_context, cl_mem_flags,
                                                      cl_GLuint, int *);
typedef cl_mem(CL_API_CALL *PFN_clCreateFromGLTexture)(
        cl_context /* context */, cl_mem_flags /* flags */, cl_GLenum /* target */,
        cl_GLint /* miplevel */, cl_GLuint /* texture */,
        cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2;
typedef cl_int(CL_API_CALL *PFN_clEnqueueAcquireGLObjects)(
        cl_command_queue /* command_queue */, cl_uint /* num_objects */,
        const cl_mem * /* mem_objects */, cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */, cl_event * /* event */);
typedef cl_int(CL_API_CALL *PFN_clEnqueueReleaseGLObjects)(
        cl_command_queue /* command_queue */, cl_uint /* num_objects */,
        const cl_mem * /* mem_objects */, cl_uint /* num_events_in_wait_list */,
        const cl_event * /* event_wait_list */,
        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;

// cl_khr_egl_event extension

// CLeglDisplayKHR is an opaque handle to an EGLDisplay
typedef void *CLeglDisplayKHR;

// CLeglSyncKHR is an opaque handle to an EGLSync object
typedef void *CLeglSyncKHR;

typedef cl_event(CL_API_CALL *PFN_clCreateEventFromEGLSyncKHR)(
        cl_context /* context */, CLeglSyncKHR /* sync */,
        CLeglDisplayKHR /* display */, cl_int * /* errcode_ret */);

// EGL sharing
typedef cl_mem(CL_API_CALL *PFN_clCreateFromEGLImageKHR)(
        cl_context /*context*/, CLeglDisplayKHR /*display*/,
        CLeglImageKHR /*image*/, cl_mem_flags /*flags*/,
        const cl_egl_image_properties_khr * /*properties*/,
        cl_int * /*errcode_ret*/);
typedef cl_int(CL_API_CALL *PFN_clEnqueueAcquireEGLObjectsKHR)(
        cl_command_queue /*command_queue*/, cl_uint /*num_objects*/,
        const cl_mem * /*mem_objects*/, cl_uint /*num_events_in_wait_list*/,
        const cl_event * /*event_wait_list*/, cl_event * /*event*/);
typedef cl_int(CL_API_CALL *PFN_clEnqueueReleaseEGLObjectsKHR)(
        cl_command_queue /*command_queue*/, cl_uint /*num_objects*/,
        const cl_mem * /*mem_objects*/, cl_uint /*num_events_in_wait_list*/,
        const cl_event * /*event_wait_list*/, cl_event * /*event*/);

extern PFN_clGetPlatformIDs clGetPlatformIDs;
extern PFN_clGetPlatformInfo clGetPlatformInfo;
extern PFN_clGetDeviceIDs clGetDeviceIDs;
extern PFN_clGetDeviceInfo clGetDeviceInfo;
extern PFN_clCreateSubDevices clCreateSubDevices;
extern PFN_clRetainDevice clRetainDevice;
extern PFN_clReleaseDevice clReleaseDevice;
extern PFN_clCreateContext clCreateContext;
extern PFN_clCreateContextFromType clCreateContextFromType;
extern PFN_clRetainContext clRetainContext;
extern PFN_clReleaseContext clReleaseContext;
extern PFN_clGetContextInfo clGetContextInfo;
extern PFN_clCreateCommandQueueWithProperties
        clCreateCommandQueueWithProperties;
extern PFN_clRetainCommandQueue clRetainCommandQueue;
extern PFN_clReleaseCommandQueue clReleaseCommandQueue;
extern PFN_clGetCommandQueueInfo clGetCommandQueueInfo;
extern PFN_clCreateBuffer clCreateBuffer;
extern PFN_clCreateSubBuffer clCreateSubBuffer;
extern PFN_clCreateImage clCreateImage;
extern PFN_clCreatePipe clCreatePipe;
extern PFN_clRetainMemObject clRetainMemObject;
extern PFN_clReleaseMemObject clReleaseMemObject;
extern PFN_clGetSupportedImageFormats clGetSupportedImageFormats;
extern PFN_clGetMemObjectInfo clGetMemObjectInfo;
extern PFN_clGetImageInfo clGetImageInfo;
extern PFN_clGetPipeInfo clGetPipeInfo;
extern PFN_clSetMemObjectDestructorCallback clSetMemObjectDestructorCallback;
extern PFN_clSVMAlloc clSVMAlloc;
extern PFN_clSVMFree clSVMFree;
extern PFN_clCreateSamplerWithProperties clCreateSamplerWithProperties;
extern PFN_clRetainSampler clRetainSampler;
extern PFN_clReleaseSampler clReleaseSampler;
extern PFN_clGetSamplerInfo clGetSamplerInfo;
extern PFN_clCreateProgramWithSource clCreateProgramWithSource;
extern PFN_clCreateProgramWithBinary clCreateProgramWithBinary;
extern PFN_clCreateProgramWithBuiltInKernels clCreateProgramWithBuiltInKernels;
extern PFN_clRetainProgram clRetainProgram;
extern PFN_clReleaseProgram clReleaseProgram;
extern PFN_clBuildProgram clBuildProgram;
extern PFN_clCompileProgram clCompileProgram;
extern PFN_clLinkProgram clLinkProgram;
extern PFN_clUnloadPlatformCompiler clUnloadPlatformCompiler;
extern PFN_clGetProgramInfo clGetProgramInfo;
extern PFN_clGetProgramBuildInfo clGetProgramBuildInfo;
extern PFN_clCreateKernel clCreateKernel;
extern PFN_clCreateKernelsInProgram clCreateKernelsInProgram;
extern PFN_clRetainKernel clRetainKernel;
extern PFN_clReleaseKernel clReleaseKernel;
extern PFN_clSetKernelArg clSetKernelArg;
extern PFN_clSetKernelArgSVMPointer clSetKernelArgSVMPointer;
extern PFN_clSetKernelExecInfo clSetKernelExecInfo;
extern PFN_clGetKernelInfo clGetKernelInfo;
extern PFN_clGetKernelArgInfo clGetKernelArgInfo;
extern PFN_clGetKernelWorkGroupInfo clGetKernelWorkGroupInfo;
extern PFN_clWaitForEvents clWaitForEvents;
extern PFN_clGetEventInfo clGetEventInfo;
extern PFN_clCreateUserEvent clCreateUserEvent;
extern PFN_clRetainEvent clRetainEvent;
extern PFN_clReleaseEvent clReleaseEvent;
extern PFN_clSetUserEventStatus clSetUserEventStatus;
extern PFN_clSetEventCallback clSetEventCallback;
extern PFN_clGetEventProfilingInfo clGetEventProfilingInfo;
extern PFN_clFlush clFlush;
extern PFN_clFinish clFinish;
extern PFN_clEnqueueReadBuffer clEnqueueReadBuffer;
extern PFN_clEnqueueReadBufferRect clEnqueueReadBufferRect;
extern PFN_clEnqueueWriteBuffer clEnqueueWriteBuffer;
extern PFN_clEnqueueWriteBufferRect clEnqueueWriteBufferRect;
extern PFN_clEnqueueFillBuffer clEnqueueFillBuffer;
extern PFN_clEnqueueCopyBuffer clEnqueueCopyBuffer;
extern PFN_clEnqueueCopyBufferRect clEnqueueCopyBufferRect;
extern PFN_clEnqueueReadImage clEnqueueReadImage;
extern PFN_clEnqueueWriteImage clEnqueueWriteImage;
extern PFN_clEnqueueFillImage clEnqueueFillImage;
extern PFN_clEnqueueCopyImage clEnqueueCopyImage;
extern PFN_clEnqueueCopyImageToBuffer clEnqueueCopyImageToBuffer;
extern PFN_clEnqueueCopyBufferToImage clEnqueueCopyBufferToImage;
extern PFN_clEnqueueMapBuffer clEnqueueMapBuffer;
extern PFN_clEnqueueMapImage clEnqueueMapImage;
extern PFN_clEnqueueUnmapMemObject clEnqueueUnmapMemObject;
extern PFN_clEnqueueMigrateMemObjects clEnqueueMigrateMemObjects;
extern PFN_clEnqueueNDRangeKernel clEnqueueNDRangeKernel;
extern PFN_clEnqueueNativeKernel clEnqueueNativeKernel;
extern PFN_clEnqueueMarkerWithWaitList clEnqueueMarkerWithWaitList;
extern PFN_clEnqueueBarrierWithWaitList clEnqueueBarrierWithWaitList;
extern PFN_clEnqueueSVMFree clEnqueueSVMFree;
extern PFN_clEnqueueSVMMemcpy clEnqueueSVMMemcpy;
extern PFN_clEnqueueSVMMemFill clEnqueueSVMMemFill;
extern PFN_clEnqueueSVMMap clEnqueueSVMMap;
extern PFN_clEnqueueSVMUnmap clEnqueueSVMUnmap;
extern PFN_clGetExtensionFunctionAddressForPlatform
        clGetExtensionFunctionAddressForPlatform;
extern PFN_clCreateImage2D clCreateImage2D;
extern PFN_clCreateImage3D clCreateImage3D;
extern PFN_clEnqueueMarker clEnqueueMarker;
extern PFN_clEnqueueWaitForEvents clEnqueueWaitForEvents;
extern PFN_clEnqueueBarrier clEnqueueBarrier;
extern PFN_clUnloadCompiler clUnloadCompiler;
extern PFN_clGetExtensionFunctionAddress clGetExtensionFunctionAddress;
extern PFN_clCreateCommandQueue clCreateCommandQueue;
extern PFN_clCreateSampler clCreateSampler;
extern PFN_clEnqueueTask clEnqueueTask;

// OpenGL sharing
extern PFN_clCreateFromGLBuffer clCreateFromGLBuffer;
extern PFN_clCreateFromGLTexture clCreateFromGLTexture;
extern PFN_clEnqueueAcquireGLObjects clEnqueueAcquireGLObjects;
extern PFN_clEnqueueReleaseGLObjects clEnqueueReleaseGLObjects;

// cl_khr_egl_event extension
extern PFN_clCreateEventFromEGLSyncKHR clCreateEventFromEGLSyncKHR;

// EGL sharing
extern PFN_clCreateFromEGLImageKHR clCreateFromEGLImageKHR;
extern PFN_clEnqueueAcquireEGLObjectsKHR clEnqueueAcquireEGLObjectsKHR;
extern PFN_clEnqueueReleaseEGLObjectsKHR clEnqueueReleaseEGLObjectsKHR;

// For convenient image creation
// It uses clCreateImage if it available (clCreateImage available since cl 1.2)
// otherwise it will use legacy clCreateImage2D
cl_mem CreateImage2DLegacy(cl_context context, cl_mem_flags flags,
                           const cl_image_format *image_format,
                           const cl_image_desc *image_desc, void *host_ptr,
                           cl_int *errcode_ret);

// It uses clCreateImage if it available (clCreateImage available since cl 1.2)
// otherwise it will use legacy clCreateImage3D
cl_mem CreateImage3DLegacy(cl_context context, cl_mem_flags flags,
                           const cl_image_format *image_format,
                           const cl_image_desc *image_desc, void *host_ptr,
                           cl_int *errcode_ret);

}

#endif //OPENCL_WRAPPER_H
